//
// Created by luxiaolu on 2025/6/9.
//

#ifndef LRU_K_H
#define LRU_K_H

/**
 * @file LRU-K.h
 * @author luxiaolu
 * @brief 
 * @version 0.1
 * @date 2025-05-18
 * 缺点：访问模式不敏感，A-B-C-D-A
 * 缓存污染：加载不再使用的内容
 * 不适用场景
 * 锁的粒度大：多线程高并发，同步等待时间开销大
 * @copyright Copyright (c) 2025
 */
# include <iostream>
# include <unordered_map>
# include <memory>
# include <mutex>
# include <cstddef>
# include "LRU.h"
template <typename Key, typename Value>
class KLruKCache : public KLruCache<Key, Value> {
    public:
        KLruKCache(size_t capacity, int history_capacity,size_t k)
                 : KLruCache<Key, Value>(capacity), k_(k),
                  history_list_(std::make_unique<KLruCache<Key, size_t>>(history_capacity)) 
                  {}
        Value get(Key key) {
            Value value{};
            // 先从主缓存获取数据
            bool inMainCache = KLruCache<Key, Value>::get(key, value);

            // 获取并更新访问历史计数
            size_t history_count = history_list_->get(key);
            history_count++;
            history_list_->put(key, history_count);

            // 如果主缓存中存在数据，则更新访问历史计数，否则从历史缓存中获取数据
            if (inMainCache) {
                return value;
            }

            if (history_count >= k_) {
                auto it = history_value_map_->find(key);
                if (it != history_value_map_->end()) {
                    Value stored_value = it->second;
                    history_list_->remove(stored_value);
                    history_value_map_->erase(it);
                    KLruCache<Key, Value>::put(key, stored_value);
                    return stored_value;
                }
            }
            // 没有历史值记录，无法添加到缓存
            return value;
        }
        

        void put(Key key, Value value) {
            Value existing_value{};
            bool in_main_cache = KLruCache<Key, Value>::get(key, existing_value);
            if (in_main_cache) {
                KLruCache<Key, Value>::put(key, value);
                return;
            }
            size_t history_count = history_list_->get(key);
            history_count++;
            history_list_->put(key, history_count);

            history_value_map_[key] = value;
            if (history_count >= k_) {
                // 添加到主缓存中
                history_list_->remove(key);
                history_value_map_.erase(key);
                KLruCache<Key, Value>::put(key, value);
            }
        }
    private:
        size_t                                 k_; // 进入缓存队列的评判标准
        std::unique_ptr<KLruCache<Key, Value>> history_list_; // 访问数据历史记录（value为访问次数）
        std::unordered_map<Key, Value>         history_value_map_; //存储未达到K次访问的数据值
};

#endif //LRU_K_H
